package com.hua.utility.utility;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class UtilString {

	public static final String className = UtilString.class.getName();

	@SuppressWarnings("rawtypes")
	private static boolean isEmpty(Object o) {
		Boolean checkResult = false;
		if (o == null) {
			checkResult = true;
		} else if (o instanceof String) {
			if ((o.toString().trim()).length() <= 0) {
				checkResult = true;
			}
		} else if (o instanceof java.util.Collection) {
			if (((java.util.Collection) o).size() <= 0) {
				checkResult = true;
			}
		} else if (o instanceof java.util.Map) {
			if (((java.util.Map) o).size() <= 0) {
				checkResult = true;
			}
		} else if (o instanceof java.lang.CharSequence) {
			if (((java.lang.CharSequence) o).length() <= 0) {
				checkResult = true;
			}
		} else {
			try {
				o.toString();
			} catch (Exception e) {
				throwRuntimeException(o.getClass().getName() + "toString forbidden operation.");
			}
		}
		return checkResult;
	}

	private static void throwRuntimeException(Object o) {
		if (isEmpty(o)) {
			return;
		} else if (o instanceof Throwable) {
			throw new RuntimeException(className + ":" + ((Throwable) o).getMessage());
		} else {
			throw new RuntimeException(className + ":" + o.toString());
		}
	}

	public static String replaceString(String mainString, String oldString, String newString) {
		if (mainString == null) {
			return null;
		}
		if (oldString == null) {
			return mainString;
		}
		if (newString == null) {
			newString = "";
		}

		int i = mainString.lastIndexOf(oldString);

		if (i < 0)
			return mainString;

		StringBuilder mainSb = new StringBuilder(mainString);

		while (i >= 0) {
			mainSb.replace(i, i + oldString.length(), newString);
			i = mainString.lastIndexOf(oldString, i - 1);
		}
		return mainSb.toString();
	}

	public static String join(List<?> list, String delim) {
		if (isEmpty(list))
			return null;
		StringBuilder buf = new StringBuilder();
		Iterator<?> i = list.iterator();

		while (i.hasNext()) {
			buf.append(i.next());
			if (i.hasNext())
				buf.append(delim);
		}
		return buf.toString();
	}

	public static List<String> split(String str, String delim) {
		List<String> splitList = null;
		StringTokenizer st = null;

		if (str == null)
			return splitList;

		if (delim != null)
			st = new StringTokenizer(str, delim);
		else
			st = new StringTokenizer(str);

		if (st != null && st.hasMoreTokens()) {
			splitList = new ArrayList<String>();

			while (st.hasMoreTokens())
				splitList.add(st.nextToken());
		}
		return splitList;
	}

	public static List<String> split(String str, String delim, int limit) {
		List<String> splitList = null;
		String[] st = null;

		if (str == null)
			return splitList;

		if (delim != null)
			st = Pattern.compile(delim).split(str, limit);
		else
			st = str.split("\\s");
		if (st != null && st.length > 0) {
			splitList = new ArrayList<String>();
			for (int i = 0; i < st.length; i++)
				splitList.add(st[i]);
		}

		return splitList;
	}

	public static Map<String, String> strToMap(String str, String delim, boolean trim) {
		return strToMap(str, delim, trim, null);

	}

	public static Map<String, String> strToMap(String str, String delim, boolean trim, String pairsSeparator) {
		if (str == null)
			return null;
		Map<String, String> decodedMap = new HashMap<String, String>();
		List<String> elements = split(str, delim);
		pairsSeparator = pairsSeparator == null ? "=" : pairsSeparator;

		for (String s : elements) {
			List<String> e = split(s, pairsSeparator);
			if (e.size() != 2) {
				continue;
			}
			String name = e.get(0);
			String value = e.get(1);
			if (trim) {
				if (name != null) {
					name = name.trim();
				}
				if (value != null) {
					value = value.trim();
				}
			}

			try {
				decodedMap.put(URLDecoder.decode(name, "UTF-8"), URLDecoder.decode(value, "UTF-8"));
			} catch (UnsupportedEncodingException e1) {
				e1.printStackTrace();
			}
		}
		return decodedMap;
	}

	public static Map<String, String> strToMap(String str, boolean trim) {
		return strToMap(str, null, trim);
	}

	public static Map<String, String> strToMap(String str, String delim) {
		return strToMap(str, delim, false);
	}

	public static Map<String, String> strToMap(String str) {
		return strToMap(str, null, false);
	}

	public static String mapToStr(Map<? extends Object, ? extends Object> map) {
		if (map == null)
			return null;
		StringBuilder buf = new StringBuilder();
		boolean first = true;

		for (Map.Entry<? extends Object, ? extends Object> entry : map.entrySet()) {
			Object key = entry.getKey();
			Object value = entry.getValue();

			if (!(key instanceof String) || !(value instanceof String))
				continue;
			String encodedName = null;
			try {
				encodedName = URLEncoder.encode((String) key, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			String encodedValue = null;
			try {
				encodedValue = URLEncoder.encode((String) value, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			if (first)
				first = false;
			else
				buf.append("|");

			buf.append(encodedName);
			buf.append("=");
			buf.append(encodedValue);
		}
		return buf.toString();
	}

	public static Map<String, String> toMap(String s) {
		Map<String, String> newMap = new HashMap<String, String>();
		if (s.startsWith("{") && s.endsWith("}")) {
			s = s.substring(1, s.length() - 1);
			String[] entries = s.split("\\,\\s");
			for (String entry : entries) {
				String[] nv = entry.split("\\=");
				newMap.put(nv[0], nv[1]);
			}
		} else {
			throw new IllegalArgumentException("String is not from Map.toString()");
		}

		return newMap;
	}

	public static List<String> toList(String s) {
		List<String> newList = new ArrayList<String>();
		if (s.startsWith("[") && s.endsWith("]")) {
			s = s.substring(1, s.length() - 1);
			String[] entries = s.split("\\,\\s");
			for (String entry : entries) {
				newList.add(entry);
			}
		} else {
			throw new IllegalArgumentException("String is not from List.toString()");
		}

		return newList;
	}

	public static Set<String> toSet(String s) {
		Set<String> newSet = new HashSet<String>();
		if (s.startsWith("[") && s.endsWith("]")) {
			s = s.substring(1, s.length() - 1);
			String[] entries = s.split("\\,\\s");
			for (String entry : entries) {
				newSet.add(entry);
			}
		} else {
			throw new IllegalArgumentException("String is not from Set.toString()");
		}

		return newSet;
	}

	public static <K, V> Map<K, V> createMap(List<K> keys, List<V> values) {
		if (keys == null || values == null || keys.size() != values.size()) {
			throw new IllegalArgumentException("Keys and Values cannot be null and must be the same size");
		}
		Map<K, V> newMap = new HashMap<K, V>();
		for (int i = 0; i < keys.size(); i++) {
			newMap.put(keys.get(i), values.get(i));
		}
		return newMap;
	}

	/** Removes all spaces from a string */
	public static String removeSpaces(String str) {
		return removeRegex(str, "[\\ ]");
	}

	private static char[] hexChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	public static int convertChar(char c) {
		if ('0' <= c && c <= '9') {
			return c - '0';
		} else if ('a' <= c && c <= 'f') {
			return c - 'a' + 0xa;
		} else if ('A' <= c && c <= 'F') {
			return c - 'A' + 0xa;
		} else {
			throw new IllegalArgumentException("Invalid hex character: [" + c + "]");
		}
	}

	public static char[] encodeInt(int i, int j, char digestChars[]) {
		if (i < 16) {
			digestChars[j] = '0';
		}
		j++;
		do {
			digestChars[j--] = hexChar[i & 0xf];
			i >>>= 4;
		} while (i != 0);
		return digestChars;
	}

	public static String removeNonNumeric(String str) {
		return removeRegex(str, "[\\D]");
	}

	public static String removeNumeric(String str) {
		return removeRegex(str, "[\\d]");
	}

	public static String removeRegex(String str, String regex) {
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		return matcher.replaceAll("");
	}

	public static String encodeQueryValue(String query) {
		String retString;
		retString = replaceString(query, "%", "%25");
		retString = replaceString(retString, " ", "%20");
		retString = replaceString(retString, "&", "%26");
		retString = replaceString(retString, "?", "%3F");
		retString = replaceString(retString, "=", "%3D");
		return retString;
	}

	public static String decodeQueryValue(String query) {
		String retString;
		retString = replaceString(query, "%25", "%");
		retString = replaceString(retString, "%20", " ");
		retString = replaceString(retString, "%26", "&");
		retString = replaceString(retString, "%3F", "?");
		retString = replaceString(retString, "%3D", "=");
		return retString;
	}

	public static String encodeXmlValue(String inString) {
		String retString = inString;
		retString = replaceString(retString, "&", "&amp;");
		retString = replaceString(retString, "<", "&lt;");
		retString = replaceString(retString, ">", "&gt;");
		retString = replaceString(retString, "\"", "&quot;");
		retString = replaceString(retString, "'", "&apos;");
		return retString;
	}

	public static String decodeXmlValue(String inString) {
		String retString = inString;
		retString = replaceString(retString, "&amp;", "&");
		retString = replaceString(retString, "&lt;", "<");
		retString = replaceString(retString, "&gt;", ">");
		retString = replaceString(retString, "&quot;", "\"");
		retString = replaceString(retString, "&apos;", "'");
		return retString;
	}

}
